package com.njtoyo.taxi.admin.logic.business;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.njtoyo.taxi.admin.library.payment.cmb.CmbPayClient;
import com.njtoyo.taxi.admin.mapper.master.entity.*;
import com.njtoyo.taxi.admin.mapper.master.enums.RideStateState;
import com.njtoyo.taxi.admin.mapper.master.mapper.*;
import com.njtoyo.taxi.admin.utils.Identifier;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;

/**
 * 退款相关
 */
@Service
@Slf4j
public class OrderRefundLogic {
    @Autowired
    private RideMapper rideMapper;
    @Autowired
    private RideOrderMapper rideOrderMapper;
    @Autowired
    private RealtimeCallMapper realtimeCallMapper;
    @Autowired
    private CallPrepayOrderMapper callPrepayOrderMapper;
    @Autowired
    private CallPrepayOrderRefundLogMapper callPrepayOrderRefundLogMapper;
    @Autowired
    private RideRefundLogMapper rideRefundLogMapper;


    /**
     * 退款
     *
     * @param callId           callId
     * @param rideId           rideId
     * @param type             call 呼叫单退款   order 订单退款
     * @param willRefundAmount 退款金额
     * @param refundType       退款类型 PART 退款部分  ALL 全部退款
     * @param refundReason     退款原因
     * @return
     */
    public boolean refund(Long callId, Long rideId, String category, String type, BigDecimal willRefundAmount, String refundType, String refundReason, String operator) {
        //计算司机 信息费用占比
        BigDecimal driverFeeRate = Convert.toBigDecimal("0.00");
        BigDecimal infoFeeRate = Convert.toBigDecimal("0.00");

        Ride ride = rideMapper.selectById(rideId);
        RideOrder rideOrder = rideOrderMapper.selectOne(Wrappers.<RideOrder>lambdaQuery().eq(RideOrder::getRideId, rideId));


        List<RideRefundLog> rideRefundLogs = rideRefundLogMapper.selectList(Wrappers.<RideRefundLog>lambdaQuery().eq(RideRefundLog::getRideId, rideId).eq(RideRefundLog::getState, 2));
        //已退金额
        BigDecimal refundedAmount = rideRefundLogs.stream().map(RideRefundLog::getRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        //预付已退
        BigDecimal prepayAmountRefund = new BigDecimal(0);
        BigDecimal orderRealAmount = new BigDecimal(0);
        if ("realtime".equals(category)) {
            RealtimeCall realtimeCall = realtimeCallMapper.selectById(callId);
            CallPrepayOrder callPrepayOrder = callPrepayOrderMapper.selectOne(Wrappers.<CallPrepayOrder>lambdaQuery().eq(CallPrepayOrder::getCallId, callId).eq(CallPrepayOrder::getCallCategory, 0));
            if (ObjectUtil.isNotNull(callPrepayOrder)) {//如果是预付单 查询已退的预付
                BigDecimal preRefundAmount = callPrepayOrderRefundLogMapper.selectRefundAmount(callPrepayOrder.getId());
                prepayAmountRefund = preRefundAmount;
                orderRealAmount = orderRealAmount.add(callPrepayOrder.getAmount().add(rideOrder.getFarePaid())).subtract(preRefundAmount);
            } else {
                orderRealAmount = rideOrder.getFarePaid();
            }
            //司机 信息费用占比
            infoFeeRate = rideOrder.getInfoServiceAmount().divide(orderRealAmount, 2, RoundingMode.HALF_UP);
            driverFeeRate = Convert.toBigDecimal("1").subtract(infoFeeRate);
            //计算司机退款金额，信息费退款金额
            BigDecimal refundDriverAmount = willRefundAmount.multiply(driverFeeRate);
            BigDecimal refundInfoAmount = willRefundAmount.multiply(infoFeeRate);
            //补钱(预付单) 非预付单就是订单付款金额
            BigDecimal addAmount = rideOrder.getFarePaid();
            //目前可退金额
            BigDecimal nowAmount = orderRealAmount.subtract(refundedAmount);
            // 剩余可退预付金额
            BigDecimal canUsePrepayAmount = ObjectUtil.isNotNull(callPrepayOrder) ? callPrepayOrder.getAmount().subtract(prepayAmountRefund) : new BigDecimal(0);
            if ("ALL".equals(refundType)) {//全额退款
                if (addAmount.compareTo(BigDecimal.ZERO) == 1) {
                    String addAmountStr = Convert.toStr(addAmount.multiply(new BigDecimal(100)).intValue());
                    //退补充的钱
                    Map<String, String> resultAddAmount = CmbPayClient.refund(getRefundId(), rideOrder.getNumber(), "退款", rideOrder.getNumber(), getRefundId(), addAmountStr, addAmountStr);
                    String errCodeAddAmount = MapUtil.getStr(resultAddAmount, "errCode");
                    if (StrUtil.isNotBlank(errCodeAddAmount)) {
                        String respMsg = MapUtil.getStr(resultAddAmount, "respMsg");
                        log.error("订单RideOrder：{},招商退预付款补充的钱返回--失败,失败原因：{}", rideOrder, respMsg);
                        return false;
                    }
                    String respCode = MapUtil.getStr(resultAddAmount, "respCode");
                    if ("SUCCESS".equals(respCode)) {
                        log.info("招商退预付款补充的钱返回--成功,开始执行退预付款...");
                        if (ObjectUtil.isNull(callPrepayOrder)) {
                            return true;
                        }
                        //退预付款的钱
                        String preAmountStr = Convert.toStr(callPrepayOrder.getAmount().multiply(new BigDecimal(100)).intValue());
                        Map<String, String> resultPreAmount = CmbPayClient.refund(getRefundId(), callPrepayOrder.getNumber(), "退款", callPrepayOrder.getNumber(), getRefundId(), preAmountStr, preAmountStr);
                        String errCodePre = MapUtil.getStr(resultPreAmount, "errCode");
                        if (StrUtil.isNotBlank(errCodePre)) {
                            String respMsg = MapUtil.getStr(resultPreAmount, "respMsg");
                            log.error("预付callPrepayOrder：{},招商退预付款返回--失败,失败原因：{}", callPrepayOrder, respMsg);
                            return false;
                        }
                        String respPreCode = MapUtil.getStr(resultPreAmount, "respCode");
                        if ("SUCCESS".equals(respPreCode)) {
                            log.info("预付callPrepayOrder：{},招商退预付款返回--成功", callPrepayOrder);
                            //保存预付款的退款记录
                            callPrepayOrderRefundLogMapper.insert(new CallPrepayOrderRefundLog()
                                    .setOrderId(callPrepayOrder.getId())
                                    .setIsSuccess(true)
                                    .setRefundAmount(rideOrder.getPrepayAmount())
                                    .setRefundNumber(callPrepayOrder.getNumber()));
                            //修改预付款退款状态
                            callPrepayOrderMapper.updateById(new CallPrepayOrder().setId(callPrepayOrder.getId()).setIsRefund(true));
                            //保存riderefundlog
//                            RideRefundLog rideRefundLog = new RideRefundLog()
//                                    .setRideId(rideId)
//                                    .setRideOrderId(rideOrder.getId())
//                                    .setCustomerId(ride.getUserId())
//                                    .setCompanyId(ride.getCompanyId())
//                                    .setCantonId(ride.getCantonId())
//                                    .setOrderNumber(rideOrder.getNumber())
//                                    .setReason(refundReason)
//                                    .setOrderAmount(rideOrder.getAmount())
//                                    .setRefundAmount(rideOrder.getActualAmount())
//                                    .setState(1)
//                                    .setOperator(operator)
//                                    .setDriverRefundAmount(rideOrder.getActualAmount())
//                                    .setCompanyRefundAmount(new BigDecimal(0))
//                                    .setPlatformRefundAmount(rideOrder.getInfoServiceAmount())
//                                    .setApplyTime(DateUtil.now())
//                                    .setCompleteTime(DateUtil.now())
//                                    .setCreatedAt(DateUtil.now())
//                                    .setUpdatedAt(DateUtil.now());
//                            rideRefundLogMapper.insert(rideRefundLog);
                            return true;
                        }
                    }
                }
            } else if ("PART".equals(refundType)) {//部分退款
                log.info("开始执行部分退款");
                if (canUsePrepayAmount.compareTo(BigDecimal.ZERO) > 0) {
                    //预付费还有可退的金额，先退预付款 判断预付费是否够退
                    if (canUsePrepayAmount.compareTo(willRefundAmount) > 0) {//够退的情况
                        String preAmt = Convert.toStr(callPrepayOrder.getAmount().multiply(new BigDecimal(100)).intValue());
                        String preAmountStr = Convert.toStr(willRefundAmount.multiply(new BigDecimal(100)).intValue());
                        String refundNumber = getRefundId();
                        Map<String, String> resultPreAmount = CmbPayClient.refund(refundNumber, rideOrder.getNumber(), "退款", rideOrder.getNumber(), refundNumber, preAmt, preAmountStr);
                        String errCodePreAmount = MapUtil.getStr(resultPreAmount, "errCode");
                        if (StrUtil.isNotBlank(errCodePreAmount)) {
                            String respMsg = MapUtil.getStr(resultPreAmount, "respMsg");
                            log.error("订单RideOrder：{},招商退预付款返回--失败,失败原因：{}", rideOrder, respMsg);
                            return false;
                        }
                        String respPreCode = MapUtil.getStr(resultPreAmount, "respCode");
                        if ("SUCCESS".equals(respPreCode)) {
                            log.info("预付callPrepayOrder：{},招商退预付款返回--成功", callPrepayOrder);
                            //保存预付款的退款记录
                            callPrepayOrderRefundLogMapper.insert(new CallPrepayOrderRefundLog()
                                    .setOrderId(callPrepayOrder.getId())
                                    .setIsSuccess(true)
                                    .setRefundAmount(rideOrder.getPrepayAmount())
                                    .setRefundNumber(callPrepayOrder.getNumber()));
//                            RideRefundLog rideRefundLog = new RideRefundLog()
//                                    .setRideId(rideId)
//                                    .setRideOrderId(rideOrder.getId())
//                                    .setCustomerId(ride.getUserId())
//                                    .setCompanyId(ride.getCompanyId())
//                                    .setCantonId(ride.getCantonId())
//                                    .setOrderNumber(rideOrder.getNumber())
//                                    .setNumber(refundNumber)
//                                    .setReason(refundReason)
//                                    .setOrderAmount(rideOrder.getAmount())
//                                    .setRefundAmount(rideOrder.getActualAmount())
//                                    .setState(1)
//                                    .setOperator(operator)
//                                    .setDriverRefundAmount(rideOrder.getActualAmount())
//                                    .setCompanyRefundAmount(new BigDecimal(0))
//                                    .setPlatformRefundAmount(rideOrder.getInfoServiceAmount())
//                                    .setApplyTime(DateUtil.now())
//                                    .setCompleteTime(DateUtil.now())
//                                    .setCreatedAt(DateUtil.now())
//                                    .setUpdatedAt(DateUtil.now());
//                            rideRefundLogMapper.insert(rideRefundLog);
                        }
                    } else {//预付不够退的情况
                        String preAmt = Convert.toStr(callPrepayOrder.getAmount().multiply(new BigDecimal(100)).intValue());
                        String preAmountStr = Convert.toStr(canUsePrepayAmount.multiply(new BigDecimal(100)).intValue());
                        //剩余需要退款金额
                        BigDecimal surplusRefund = willRefundAmount.subtract(canUsePrepayAmount);
                        //先把预付退完
                        String refundNumber = getRefundId();
                        Map<String, String> resultPreAmount = CmbPayClient.refund(refundNumber, rideOrder.getNumber(), "退款", rideOrder.getNumber(), refundNumber, preAmt, preAmountStr);
                        String errCodePreAmount = MapUtil.getStr(resultPreAmount, "errCode");
                        if (StrUtil.isNotBlank(errCodePreAmount)) {
                            String respMsg = MapUtil.getStr(resultPreAmount, "respMsg");
                            log.error("订单RideOrder：{},招商退预付款返回--失败,失败原因：{}", rideOrder, respMsg);
                            return false;
                        }
                        String respPreCode = MapUtil.getStr(resultPreAmount, "respCode");
                        if ("SUCCESS".equals(respPreCode)) {//接着从ride0rder退剩余的
                            String refundNumberOrder = getRefundId();
                            String amtOrder = Convert.toStr(rideOrder.getFarePaid().multiply(new BigDecimal(100)).intValue());
                            String refundAmountOrder = Convert.toStr(surplusRefund.multiply(new BigDecimal(100)).intValue());
                            Map<String, String> resultPreAmountOrder = CmbPayClient.refund(refundNumberOrder, rideOrder.getNumber(), "退款", rideOrder.getNumber(), refundNumberOrder, amtOrder, refundAmountOrder);
                            String errCodePreAmountOrder = MapUtil.getStr(resultPreAmountOrder, "errCode");
                            if (StrUtil.isNotBlank(errCodePreAmountOrder)) {
                                String respMsg = MapUtil.getStr(resultPreAmountOrder, "respMsg");
                                log.error("订单RideOrder：{},招商退预付款返回--失败,失败原因：{}", rideOrder, respMsg);
                                return false;
                            }
                            String respOrderCode = MapUtil.getStr(resultPreAmountOrder, "respCode");
                            //退成功
                            if ("SUCCESS".equals(respOrderCode)) {
//                                RideRefundLog rideRefundLog = new RideRefundLog()
//                                        .setRideId(rideId)
//                                        .setRideOrderId(rideOrder.getId())
//                                        .setCustomerId(ride.getUserId())
//                                        .setCompanyId(ride.getCompanyId())
//                                        .setCantonId(ride.getCantonId())
//                                        .setOrderNumber(rideOrder.getNumber())
//                                        .setNumber(refundNumber)
//                                        .setReason(refundReason)
//                                        .setOrderAmount(rideOrder.getAmount())
//                                        .setRefundAmount(willRefundAmount)
//                                        .setState(2)
//                                        .setOperator(operator)
//                                        .setDriverRefundAmount(refundDriverAmount)
//                                        .setCompanyRefundAmount(new BigDecimal(0))
//                                        .setPlatformRefundAmount(refundInfoAmount)
//                                        .setApplyTime(DateUtil.now())
//                                        .setCompleteTime(DateUtil.now())
//                                        .setCreatedAt(DateUtil.now())
//                                        .setUpdatedAt(DateUtil.now());
//                                rideRefundLogMapper.insert(rideRefundLog);
                            }
                        }
                    }
                }
            }
        }
        return true;
    }


    private String getRefundId() {
        Identifier idg = new Identifier("R");
        return idg.generate();
    }


}
